import axios from 'axios'
import router from '@/router'

// create an axios instance
const service = axios.create({
    baseURL: import.meta.env.VITE_BASE_URL,
    timeout: 60000 // request timeout
})

const reg = RegExp('/auth')
const reg1 = RegExp('/global/region')
const reg2 = RegExp('/global/jurisdiction')
const reg3 = RegExp('/log')
// 权限接口
const authUrlList = [
    '/constant/logoutType/list',
    '/constant/returnStatus/list',
    '/login',
    '/logout',
    '/menu',
    '/menuNode',
    '/refreshToken',
    '/sysdate',
    '/lockToken',
    '/unlockToken',
    '/verifyTokenLocked',
    '/mobileVerificationCode',
    '/loginByVerificationCode',
    '/communal/interface/listJurisdiction'
]
// smooth接口
const smoothUrl = [
    '/global/globalApplicationParameter/findApplicationTitle',
    '/register/crossing/listCrossingCoordinatePackageAll'
]
const gisUrl = [
    '/v2x/path/plan'
]

const cmmsUrl = [
    '/deployDevice/report/export'
]

// 请求拦截
service.interceptors.request.use(
  config => {
      const userStore = useUserStore()
      // 权限基本地址和Smooth区分
      if (config.url.match(reg) || config.url.match(reg1) || config.url.match(reg2) || config.url.match(reg3) || authUrlList.includes(config.url)) {
          config.baseURL = '/auth'
      } else if (smoothUrl.includes(config.url)) {
          config.baseURL = process.env.NODE_ENV === 'production' ? '/smooths' : '/smooth'
      } else if (cmmsUrl.includes(config.url)) {
          config.baseURL = '/cmms_schedule'
      } else if (gisUrl.includes(config.url)) {
          config.baseURL = '/gis'
      }
      if (userStore.accessToken) {
          // let each request carry token
          // ['X-Token'] is a custom headers key
          // please modify it according to the actual situation
          config.headers['Authorization'] = getCookieAccessToken()
          // config.headers['Gateway_Header'] = 'gateway.key.lee'
      }
      // 对get请求的参数全部进行URL编码
      let url = config.url
      if (config.method === 'get' && config.params) {
          url += '?'
          let keys = Object.keys(config.params)
          for (let key of keys) {
              url += `${key}=${encodeURIComponent(config.params[key])}&`
          }
          url = url.substring(0, url.length - 1)
          config.params = {}
      }
      config.url = url
      // 下载进度配置
      if (config.downloadProgress) {
          /* config.onDownloadProgress = progressEvent =>
           handleProcess(progressEvent, config.downloadProgress)*/
          config.onDownloadProgress = config.downloadProgress // 回调函数 参数为progressEvent
      }
      // 上传进度配置
      if (config.uploadProgress) {
          config.onUploadProgress = config.uploadProgress
          /* config.onUploadProgress = progressEvent =>
           handleProcess(progressEvent, config.uploadProgress)*/
      }
      return config
  },
  error => {
      // do something with request error
      console.log(error) // for debug
      return Promise.reject(error)
  }
)

function refreshToken(rToken) {
    // service是当前request.js中已创建的axios实例
    return service.get('/refreshToken', {params: {token: rToken}}).then(res => res.data)
}

// 是否正在刷新的标记
let isRefreshing = false
// 重试队列，每一项将是一个待执行的函数形式
let requestList = []
// 响应拦截
service.interceptors.response.use(
  response => {
      const userStore = useUserStore()
      const res = response.data
      // token刷新处理
      if (res.code === 421) {
          const config = response.config
          if (!isRefreshing) {
              // 不在刷新刷新标识位置为true
              isRefreshing = true
              refreshToken(getCookieRefreshToken()).then(response => {
                  const {accessToken, refreshToken} = response
                  userStore.setStoreAccessToken(accessToken) // 将token更新到store
                  userStore.setStoreRefreshTokenToken(refreshToken)// 将refreshToken更新到store
                  // 已经刷新了token，将所有队列中的请求进行重试
                  requestList.forEach(cb => cb(accessToken))
                  requestList = []
                  // 刷新结束
                  isRefreshing = false
                  // 重新请求
                  return service(config)
              }).catch(() => {
                  userStore.logout().then(() => {
                      router.push({path: '/login'})
                      ElMessage.closeAll()
                  })
              })
          }
          // 将所有请求暂存与请求队列中，利用promise的pending状态
          // 核心代码逻辑： 只要promise中的resolve没有调用，他会一直处于pending状态
          return new Promise((resolve) => {
              // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
              requestList.push((token) => {
                  // 重置baseUrl 特别注意：如果不重置会出现/api/api
                  // config.baseURL = ''
                  // 更新token
                  config.headers['Authorization'] = token
                  // 将promise.resolve塞入队列
                  resolve(service(config))
              })
          })
      }
      if (res.code === 401) { // token过期
          userStore.out().then(() => {
              router.push({path: '/login'})
              ElMessage.closeAll()
          })
          return false
      }
      if (res.code === 11000 && router.currentRoute.value.path !== '/login') { // 用户不存在 (被删除)
          userStore.out().then(() => {
              router.push({path: '/login'})
              ElMessage.closeAll()
          })
          return false
      }
      if (res.code === 11008 && router.currentRoute.value.path !== '/login') { // 用户已被禁止登录 (被锁定)
          userStore.out().then(() => {
              router.push({path: '/login'})
              ElMessage.closeAll()
          })
          return false
      }
      if (res.code === 11007 && router.currentRoute.value.path !== '/login') { // 用户注册信息已过期 (有效时间过期)
          userStore.out().then(() => {
              router.push({path: '/login'})
              ElMessage.closeAll()
          })
          return false
      }

      // 返回结果
      return Promise.resolve(res)
  },
  error => {
      ElMessage.closeAll()
      console.log(error)
      const {status, path, message} = error.response.data
      if (status === 404) {
          // Emessage('error', `"${ path }"` + error.response.data.error)
      } else {
          // Emessage('error', message)
      }
      // return Promise.reject(error)
      return Promise.resolve(error)
  }
)
export default service
